﻿/******************************************************************************************
 
Made by www.Flashphoner.com, all rights reserved.
These sources can only be used for working with Flashphoner server.
If you want use this to create your own application (separate from Flashphoner server) – 
please contact support@flashphoner.com 

******************************************************************************************/

package com.flashphoner.api
{
	import com.flashphoner.api.data.ErrorCodes;
	import com.flashphoner.api.data.ModelLocator;
	import com.flashphoner.api.data.PhoneConfig;
	import com.flashphoner.api.interfaces.API;
	import com.flashphoner.api.interfaces.APINotify;
	import com.flashphoner.api.js.APINotifyJS;
	import com.flashphoner.api.management.PhoneSpeaker;
	import com.flashphoner.api.management.SoundControl;
	import com.flashphoner.api.management.VideoControl;
	
	import flash.events.TimerEvent;
	import flash.external.ExternalInterface;
	import flash.media.Camera;
	import flash.media.Microphone;
	import flash.net.Responder;
	import flash.utils.Timer;
	
	import mx.collections.ArrayCollection;

	[Bindable]
	public class Flash_API
	{
		private var registeredTimer:Timer;

		internal var phoneServerProxy:PhoneServerProxy;
		
		public var calls:ArrayCollection;	
		
		internal var apiNotify:APINotify;		

		public var modelLocator:ModelLocator;
		
		public static function initLibrary():void{
			PhoneModel.getInstance();
		}
		
		public function Flash_API(){
			PhoneModel.getInstance();
			/*ExternalInterface.addCallback("getParameters",flash_API.getParameters);
			ExternalInterface.addCallback("login",flash_API.login);
			ExternalInterface.addCallback("loginClick2Call",flash_API.loginClick2Call);
			ExternalInterface.addCallback("call",flash_API.call);
			ExternalInterface.addCallback("hangup",flash_API.hangup);
			ExternalInterface.addCallback("answer",flash_API.answer);
			ExternalInterface.addCallback("sendDTMF",flash_API.sendDTMF);
			ExternalInterface.addCallback("getMicVolume",flash_API.getMicVolume);
			ExternalInterface.addCallback("setMicVolume",flash_API.setMicVolume);
			ExternalInterface.addCallback("getVolume",flash_API.getVolume);
			ExternalInterface.addCallback("setVolume",flash_API.setVolume);
			ExternalInterface.addCallback("getMicropones",flash_API.getMicropones);
			ExternalInterface.addCallback("setMicrophone",flash_API.setMicrophone);
			ExternalInterface.addCallback("getCameras",flash_API.getCameras);
			ExternalInterface.addCallback("setCamera",flash_API.setCamera);
			ExternalInterface.addCallback("logoff",flash_API.logoff);
			addAPINotify(new APINotifyJS());*/
			calls = new ArrayCollection();
			modelLocator = new ModelLocator();
			phoneServerProxy = new PhoneServerProxy(new Responder(result),this);
		}
		
		public function getCurrentCall():Call{
			for each(var obj:* in calls){
				if (obj.state == Call.STATE_TALK){
					return Call(obj);	
				}
			}
			return null;
		}
			
		public function getCallById(callId:String):Call{
			for each(var obj:* in calls){
				if (obj.id == callId){
					return Call(obj);
				}
			}
			return null;
		}

		public function getCallByIndex(index:Number):Call{
			var obj:* = calls.getItemAt(index);
			if (obj != null){
				return Call(obj);	
			}
			return null;
		}		
		
		public function getIndexByCallId(callId:String):Number{
			for (var index:* in calls){
				var obj:* = calls.getItemAt(index);
				if (obj.id == callId){
					return index;
				}
			}
			return null;
		}	
		
		internal function addCall(call:Call):void{
			for (var index:* in calls){
				var obj:* = calls.getItemAt(index);
				if (obj.id == call.id){
					return;
				}
			}
			calls.addItem(call);
		}
		
		internal function removeCall(callId:String):void{
			for (var index:* in calls){
				var obj:* = calls.getItemAt(index);
				if (obj.id == callId){
					calls.removeItemAt(index);
				}
			}
		}
		
		public function getPhoneSpeaker():PhoneSpeaker{
			return this.phoneServerProxy.phoneSpeaker;
		}
		
		public function addAPINotify(apiNotify:APINotify):void{
			this.apiNotify = apiNotify;
		}
		
		public function getParameters():Object{
			var object:Object = PhoneModel.getInstance().parameters;
			if (object == null){
				return ErrorCodes.PARAMETERS_IS_NOT_INITIALIZED;				
			}else{
				return PhoneModel.getInstance().parameters;
			}
		}
		public function login(username:String,password:String):int{
			ExternalInterface.call("notifyRegisterRequired",PhoneConfig.REGISTER_REQUIRED);
			if (PhoneConfig.REGISTER_REQUIRED){
				upRegisteredTimer();
				startRegisterTimer();
			}
			return phoneServerProxy.login(username,password);							
		}
		
		public function loginClick2Call():void{
			ExternalInterface.call("notifyRegisterRequired",PhoneConfig.REGISTER_REQUIRED);
			if (PhoneConfig.REGISTER_REQUIRED){
				upRegisteredTimer();
				startRegisterTimer();
			}
			phoneServerProxy.login();							
		}		
		
		public function call(callee:String, visibleName:String, isVideoCall:Boolean = false):int{
			if (PhoneConfig.CHECK_VALIDATION_CALLEE){
				var reg:RegExp = /[a-zа-яё]/i;
				if (callee != null && callee != ""){
					if (modelLocator.mode == "flashphoner"){
						if ((callee.indexOf("sip:") == 0)){
							if (callee.indexOf("@") == -1 || callee.indexOf("@") == callee.length-1){
								return 1;
							}
						}else{
							if (callee.search(reg) != -1){
								if (callee.indexOf("@") != -1){
									return 1;
								}
								if (callee.indexOf(":") != -1){
									return 1;
								}
								callee = "sip:"+callee+"@"+modelLocator.sipProviderAddress+":"+modelLocator.sipProviderPort;
							}
						}
					}else{
						return 1;
					}
				}else{
					if (modelLocator.mode != "click2call"){
						return 1;
					}
				}
			}
			if (visibleName != null){
				visibleName.replace("\"","");
				visibleName.replace("\'","");
			}
			for each (var tempCall:Call in calls){
				if (tempCall.state == Call.STATE_TALK){
					tempCall.setStatusHold(true);
				}
			}
			phoneServerProxy.call(visibleName,callee,isVideoCall);
			return 0;
		}		
		
		public function getMicVolume():int{
			return SoundControl.getInstance().getMicrophone().gain;
		}
		
		public function setMicVolume(volume:int):void{
			SoundControl.getInstance().getMicrophone().gain = volume;
		}
		
		public function getVolume():int{
			return phoneServerProxy.phoneSpeaker.getVolume();
		}
		
		public function setVolume(volume:int):void{
			phoneServerProxy.phoneSpeaker.setVolume(volume);
		}
		
		public function getMicropones():Array{
			return Microphone.names;
		}
		
		public function setMicrophone(name:String):void{
			var i:int = 0;
			for each (var nameMic:String in Microphone.names){
				if (nameMic == name){
					SoundControl.getInstance().changeMicrophone(Microphone.getMicrophone(i),false);
					return;						
				}
				i++;				
			}
		}
		
		public function getCameras():Array{
			return Camera.names;
		}
		
		public function setCamera(name:String):void{
			VideoControl.getInstance().changeCamera(Camera.getCamera(name));
		}
		
		public  function logoff():void{
			phoneServerProxy.disconnect();
		}
		
		internal function startRegisterTimer():void{
			registeredTimer.start();	
		}
		
		
		internal function upRegisteredTimer():void{
			if (registeredTimer!=null){
				registeredTimer.stop();
			} else {
				registeredTimer = new Timer(13000);
				registeredTimer.addEventListener(TimerEvent.TIMER,registeredExpire);					
			}
		}
		
		internal function dropRegisteredTimer():void{
			if (registeredTimer!=null){
				registeredTimer.stop();
				registeredTimer.removeEventListener(TimerEvent.TIMER,registeredExpire);
				registeredTimer=null;
			}
		}
		
		private function registeredExpire(event:TimerEvent):void{
			apiNotify.notifyError(ErrorCodes.REGISTER_EXPIRE);			
			dropRegisteredTimer();			
		}			
		
		private function result(_call : Object) : void
		{
			var call:Call = new Call(this);
			call.id = _call.id;
			call.state = _call.state;
			call.incoming=false;							
			addCall(call);
		}		
		

	}
}